package com.dalin.framework.common.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import com.dalin.framework.common.utils.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.dalin.framework.common.PropertyConst;

/*****************************************************************************
 * @content: 文件操作常用方法汇总                                                                                                                                         *
 * @author : 那建林                                                                                                                                                                  *
 * @crtDate: 2010-01-19                                                     *
 ****************************************************************************/
public final class FileUtils {
	private FileUtils() {} // 不允许构造
	private static final Log log = LogFactory.getLog(FileUtils.class);
	
	public static void main(String[] args) {
	}
	
	
	/**************************************************************************
	 * @describe: 
	 * @param   :
	 * @return  : String
	 * @author  : najianlin
	 * @crtDate : ${date} ${time}
     * @remark  : 
     *  najianlin modify it at ${date} ${time} because: 
     *                       
	 */
	public static File findFileByName(String fileName, File rootFile) {
		if (rootFile == null) rootFile = new File("A:/");
		if (rootFile.getName().equals(fileName)) {
			System.out.println("=============="+rootFile.getAbsolutePath());
		}
		if (rootFile.isDirectory() && !rootFile.getName().equals("System Volume Information")) {
			try {
				for (File f : rootFile.listFiles()) {
					findFileByName(fileName, f);
				}
			} catch (Exception e) {
				System.out.println(rootFile.getAbsolutePath());
				e.printStackTrace();
			}
			
		}
		return rootFile;
	}
	/***************************************************************************
	 * @content: 取得当前WEB工程名
	 * @return : String
	 * @author : 那建林
	 * @crtDate: 2012-03-11
	 */
	public static String getCurrentWebPN() {
		String rtnStr = FileUtils.class.getResource("/").toString();
		int i = rtnStr.toUpperCase().indexOf("/WEB-INF/CLASSES");
		rtnStr = rtnStr.substring(0, i);
        return rtnStr.substring(rtnStr.lastIndexOf("/") + 1);
    } 
	
	
	/***************************************************************************
	 * @content: 取得当前工程的class绝对路径
	 * @return : String,返回格式：/c:/tt/dd/WebRoot/WEB-INF/classes/
	 * @author : 那建林
	 * @crtDate: 2012-03-11
	 */
	public static String getResourcePath() {
        String rtnStr = FileUtils.class.getResource("/").toString();
        rtnStr = rtnStr.replace("file:/", "")
        			.replaceAll("%20", " ");
        rtnStr = "/" + rtnStr;
        return rtnStr;
    } 
	
	
	/*************************************************************************
	 * @content: 得到此文件的BufferedInputStream
	 * @param  : file 文件路径
	 * @retrun : BufferedInputStream
	 * @author : 那建林
	 * @crtDate: 2010-03-14
	 * @modDate: 2010-03-14
	 */
	public static BufferedInputStream newBufferedInputStream(File file) throws FileNotFoundException {
        if (!file.isFile()) {
        	throw new FileNotFoundException("File '" + file + "' does not exist");
        }
		return new BufferedInputStream(new FileInputStream(file));
    }
	
	
	/*************************************************************************
	 * @content: 得到此文件的BufferedOutputStream
	 * @param  : file 文件路径
	 * @retrun : BufferedOutputStream
	 * @author : 那建林
	 * @crtDate: 2010-03-14
	 * @modDate: 2010-03-14
	 */
	public static BufferedOutputStream newBufferedOutputStream(File file) throws FileNotFoundException {
		return new BufferedOutputStream(new FileOutputStream(file));
    }
	
	
	/*************************************************************************
	 * @content: 得到文件路径最后一个分隔符的位置
	 * @param  : filePath 文件路径
	 * @retrun : int 分隔符的位置
	 * @author : 那建林
	 * @crtDate: 2010-03-12
	 * @modDate: 2010-03-12
	 */
	public static int indexOfLastSeparator(String filePath) {
        if (StringUtils.isBlank(filePath)) {
            return -1;
        }
        int lastUnixPos = filePath.lastIndexOf(PropertyConst.SINGLE_SLASH);
        int lastWindowsPos = filePath
        	.lastIndexOf(PropertyConst.SINGLE_BACKSLASH);
        return Math.max(lastUnixPos, lastWindowsPos);
    }
	
	
	/*************************************************************************
	 * @content: 根据文件路径解析出文件名称, 不包括后缀名称
	 * @param  : path 文件路径
	 * @retrun : String 文件名
	 * @author : 那建林
	 * @crtDate: 2010-01-21
	 * @modDate: 2010-01-21
	 */
	public static String getFileName(String filePath) {
		if (StringUtils.isBlank(filePath)) {
			throw new NullPointerException("Parameter 'filePath' is null");
		}
		return filePath.substring(indexOfLastSeparator(filePath) + 1)
				.replace("." + getFileExtention(filePath), "");
	}
	
	
	/*************************************************************************
	 * @content: 获得文件的扩展名
	 * @modify : 写工具类考虑问题要全面，参数为空得不到正确的值要显示异常
	 * @param  : fileName 文件名或文件全路径名
	 * @return : String 文件扩展名
	 * @author : 那建林
	 * @crtDate: 2010-01-20
	 * @modDate: 2010-03-12
	 */
	public static String getFileExtention(String fileName)  {
		if (StringUtils.isBlank(fileName)) {
			throw new NullPointerException("Parameter 'fileName' is null");
		}
		String[] strArray = fileName.split(PropertyConst.SINGLE_BACKSLASH_DOT);
		if (strArray.length == 1) return null;
        return strArray[strArray.length - 1];
	}
	public static String getFileExtention(File file) {
		return getFileExtention(file.getPath());
	} 
	
	
	/*************************************************************************
	 * @content: 获得文件的的编码格式,utf-8/gbk/gb2312还是什么？
	 * @param  : file 待判断的文件
	 * @return : String 编码类型
	 * @author : 那建林
	 * @crtDate: 2010-03-16
	 * @modDate: 2010-03-16
	 */
	public static String getFileEncoding(File file) {
		
		return null;
	} 
	
	
	/*************************************************************************
	 * @content: 重命名文件名
	 * @modify : 加个多态方法,参数为空直接返回false
	 * @param  : oldFilePath 文件的路径
	 * @param  : newName 新的文件名（包括后缀名）
	 * @return : boolean 重命名成功与否
	 * @author : 那建林
	 * @crtDate: 2010-01-19
	 * @modDate: 2010-03-12
	 */
	public static boolean renameFile(File oldFile, String newName) {
		if (!oldFile.exists()) {
			log.error(oldFile.getAbsolutePath() + " does not exit.");
			return false;
		}
		if (StringUtils.isBlank(newName)) {
			log.error("Parameter 'newName' is null.");
			return false;
		}
		File newFile = new File(oldFile.getParent() + File.separator + newName);
		return oldFile.renameTo(newFile);
	}
	
	
	/*************************************************************************
	 * @content: 查询给定参数目录是否有子文件或目录
	 * @param  : rootPath 待查询的目录
	 * @return : boolean 是否含有子文件或目录
	 * @author : 那建林
	 * @crtDate: 2010-01-13
	 * @modDate: 2010-03-13
	 */
	public static boolean hasSubFiles(File rootDir) throws Exception {
		return rootDir.isDirectory() 
				&& getAllDirsAndFiles(rootDir).size() > 1;
	}
	
	/*************************************************************************
	 * @content: 获得参数路径下的所有目录和文件的集合,如果是目录包括目录本身
	 * @modify : 加多态方法和不能得到正确值时的异常信息
	 * @param  : rootPath 待查询的目录
	 * @return : List<File> 目录和文件的集合
	 * @author : 那建林
	 * @crtDate: 2010-01-19
	 * @modDate: 2010-03-12
	 */
	public static List<File> getAllDirsAndFiles(File rootDirOrFile) {
		List<File> rtnList = new ArrayList<File>();
		if (rootDirOrFile.isFile()) {
			rtnList.add(rootDirOrFile);
		}
		if (rootDirOrFile.isDirectory()) {
			rtnList.add(rootDirOrFile);
			for (File f : rootDirOrFile.listFiles()) {
				rtnList.addAll(getAllDirsAndFiles(f));
			}
		}
		return rtnList;
	}
	
	
	/*************************************************************************
	 * @content: 获得参数路径下的所有目录的集合
	 * @param  : rootPath 待查询的目录
	 * @return : List<File> 目录的集合
	 * @author : 那建林
	 * @crtDate: 2010-01-19
	 * @modDate: 2010-01-19
	 */
	public static List<File> getAllDirs(File rootDir) {
		List<File> allDirList = getAllDirsAndFiles(rootDir);
		for (int i = 0; i < allDirList.size(); i++) {
			if (!allDirList.get(i).isDirectory()) {
				allDirList.remove(i);
				i--;
			}
		}
		return allDirList;
	}
	
	
	/*************************************************************************
	 * @content: 获得参数路径及子目录下的所有文件,不包括目录
	 * @param  : rootPath 待查询的目录
	 * @return : List<File> 文件的集合
	 * @author : 那建林
	 * @crtDate: 2010-01-19
	 * @modDate: 2010-03-12
	 */
	public static List<File> getAllFiles(File rootDir) {
		List<File> allFileList = getAllDirsAndFiles(rootDir);
		for (int i = 0; i < allFileList.size(); i++) {
			if (!allFileList.get(i).isFile()) {
				allFileList.remove(i);
				i--;
			}
		}
		return allFileList;
	}

	
	/*************************************************************************
	 * @content: 删除给定文件或目录(当然包括目录下所有文件）
	 * @param  : delPath 待删除的文件或目录
	 * @return : void
	 * @author : 那建林
	 * @crtDate: 2010-01-19
	 * @modDate: 2010-01-19
	 */
	public static void deleteFiles(File delDirOrFile) {
		List<File> allFileList = FileUtils.getAllDirsAndFiles(delDirOrFile);
		File f = null;
		for (int i = allFileList.size() - 1; i > -1; i--) {
			f = allFileList.get(i);
			if (f.exists() && !f.delete()) {
				allFileList.remove(i);
				i--;
			}
		}
	}
	
	
	/*************************************************************************
	 * @content: 文件另存为它处,如果存在目标文件为覆盖
	 * @param  : srcFile 源文件
	 * @param  : destFile 目标文件
	 * @author : 那建林
	 * @crtDate: 2010-03-13
	 * @modDate: 2010-03-13
	 */
	public static void saveAsFile(
			File srcFile, File destFile) throws Exception {
		if (!srcFile.isFile()) {
			throw new FileNotFoundException("Source '" + srcFile + "' does not exist or not a file.");
		}
		saveAsFile(new FileInputStream(srcFile), destFile);
	}
	public static void saveAsFile(InputStream in, File destFile) throws Exception {
		File parentFile = destFile.getParentFile();
		parentFile.mkdirs();
		IoUtils.store(in, newBufferedOutputStream(destFile));
	}
	
	
	
	/*************************************************************************
	 * @content: copy srcPath文件或文件夹　到　destPath目录下,默认为覆盖
	 * @param  : srcDirOrFile 待copy的目录或文件
	 * @param  : destDir 目标目录
	 * @return : List<File> 移动成功的文件集合
	 * @author : 那建林
	 * @crtDate: 2010-01-19
	 * @modDate: 2010-01-19
	 */
	public static List<File> moveFilesToDir(
			File srcDirOrFile, File destDir) throws Exception {
		return moveFilesToDir(srcDirOrFile, destDir, true);
	}
	public static List<File> moveFilesToDir(File srcDirOrFile, 
			File destDir, boolean isOverwrited) throws Exception {
		if (!srcDirOrFile.exists()) {
			 throw new FileNotFoundException("Source '" + srcDirOrFile + "' does not exist");
		}
		destDir.mkdirs();
	    if (!destDir.isDirectory()) {
            throw new IOException("Directory '" + destDir + "' creats failed.");
        }
		int parentLength = srcDirOrFile.getParent().length();
		String destRootPath = destDir.getAbsolutePath();
		List<File> allList = FileUtils.getAllDirsAndFiles(srcDirOrFile);
		for (int i = 0; i < allList.size(); i++) {
			srcDirOrFile = allList.get(i);
			String toPath = destRootPath + srcDirOrFile.getAbsolutePath()
					.substring(parentLength);
			destDir = new File(toPath);
			if (destDir.exists() && !isOverwrited) {
				allList.remove(i);
				i--;
				continue;
			}
			if (srcDirOrFile.isDirectory()) {
				destDir.mkdirs();
			} else {
				saveAsFile(srcDirOrFile, destDir);
			}
		}
		return allList;
	}
	
	
	/*************************************************************************
	 * @content: cut srcPath文件或文件夹　到　destDir目录下
	 * @param  : srcPath 待cut的目录或文件
	 * @param  : destDir 目标目录
	 * @return : List<File> 剪切成功的文件集合
	 * @author : 那建林
	 * @crtDate: 2010-01-19
	 * @modDate: 2010-01-19
	 */
	public static List<File> cutFiles(File srcDirOrFile, File destDir) throws Exception {
		return cutFiles(srcDirOrFile, destDir, true);
	}
	public static List<File> cutFiles(File srcDirOrFile, File destDir, boolean isOverwrited) throws Exception {
		List<File> rtnList = null;
		if (isOverwrited) {
			rtnList = moveFilesToDir(srcDirOrFile, destDir);
			deleteFiles(srcDirOrFile);
		} else {
			rtnList = moveFilesToDir(srcDirOrFile, destDir, false);
			File f = null;
			for (int i = rtnList.size() - 1; i > -1; i--) {
				f = rtnList.get(i);
				f.delete();
			}
		}
		return rtnList;
	}
	
	
	/*************************************************************************
	 * @content: dalin文件分割
	 * @param  : srcFile 待分割文件
	 * @param  : splitNum 分割的份数
	 * @author : 那建林
	 * @crtDate: 2010-03-16
	 * @modDate: 2010-03-16
	 */
	public static void splitFile(File srcFile, int splitNum) throws Exception {
		
	}
	
	
	/*************************************************************************
	 * @content: dalin文件分割整合
	 * @param  : srcDir 待整合的文件目录
	 * @param  : destFile 目标文件
	 * @author : 那建林
	 * @crtDate: 2010-03-16
	 * @modDate: 2010-03-16
	 */
	public static void mergeFiles(File srcDir, File destFile) throws Exception {
		
	}
	
	
	/*************************************************************************
	 * @content: 压缩文件或文件夹到destFile文件，如将c:\temp文件夹压缩到d:\aa.zip
	 * @modify : 重构
	 * @param  : srcPath 待压缩的文件或目录
	 * @param  : destFile 目标文件
	 * @author : 那建林
	 * @crtDate: 2010-01-21
	 * @modDate: 2010-03-13
	 */
	public static void zipFiles(
			File srcDirOrFile, File destFile) throws Exception {
		if (!srcDirOrFile.exists()) {
			 throw new FileNotFoundException("Source '"
					+ srcDirOrFile + "' does not exist");
		}
		String destFileName = destFile.getName();
		if (!destFileName.endsWith(".zip") && !destFileName.endsWith(".rar")) {
			throw new IllegalArgumentException("文件名后缀名必须为[zip或rar]形式");
		}
		int parentLength = srcDirOrFile.getParent().length();
		File destParentFile = new File(destFile.getParent());
		destParentFile.mkdirs();
		ZipOutputStream zos = new ZipOutputStream(
				new FileOutputStream(destFile));
		ZipEntry zipEntry = null;
		List<File> dirsAndFilesList = getAllDirsAndFiles(srcDirOrFile);
		for (File f : dirsAndFilesList) {
			String filePath = f.getAbsolutePath().substring(parentLength + 1);
			if (f.isDirectory()) {
				zipEntry = new ZipEntry(filePath + PropertyConst.SINGLE_SLASH);
				zipEntry.setTime(f.lastModified());
				zos.putNextEntry(zipEntry);
			} else {
				zipEntry = new ZipEntry(filePath);
				zipEntry.setTime(f.lastModified());
				zipEntry.setSize(f.length());
				zos.putNextEntry(zipEntry);
				IoUtils.store(newBufferedInputStream(f), zos);
			}
		}
		zos.close();
		log.debug(srcDirOrFile + "压缩结束");
	} // ends method
	
	
	/*************************************************************************
	 * @content: 解压缩文件至destDir目录
	 * @modify : 重构
	 * @param  : srcFile 待解压缩的文件
	 * @param  : destDir 目标目录
	 * @author : 那建林
	 * @crtDate: 2010-01-21
	 * @modDate: 2010-03-13
	 */
	public static void unzipFile(
			File srcFile, File destDir) throws Exception {
		String srcFileName = srcFile.getName();
		if (!srcFileName.endsWith(".zip") && !srcFileName.endsWith(".rar")) {
			//throw new IllegalArgumentException("文件名后缀名必须为[zip或rar]形式");
			//上传文件时是临时name,所以注释掉
		}
		if (destDir.exists()) {
			deleteFiles(destDir);
		}
		destDir.mkdirs();
		String destPath = destDir.getAbsolutePath() 
				+ PropertyConst.SINGLE_SLASH;
		ZipFile zipFile = new ZipFile(srcFile);
		Enumeration enume = zipFile.entries();
		ZipEntry entry = null;
		FileOutputStream fos = null;
		while (enume.hasMoreElements()) {
			entry = (ZipEntry) enume.nextElement();
			destDir = new File(destPath + entry.getName());
			if (entry.isDirectory()) {
				destDir.mkdirs();
			} else {
				fos = new FileOutputStream(destDir);
				IoUtils.store(zipFile.getInputStream(entry), new BufferedOutputStream(fos));
				fos.close();
			}
			destDir.setLastModified(entry.getTime());
		}
		log.debug(srcFile + "解压缩结束");
	}
	
	// 转pdf文件
}

